package xyz.wbsite.zentao.sdk.task;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.StaticLog;
import xyz.wbsite.zentao.sdk.Constant;
import xyz.wbsite.zentao.sdk.ZentaoInstance;
import xyz.wbsite.zentao.sdk.task.ent.ZtTask;
import xyz.wbsite.zentao.sdk.task.req.ZtTaskCloseRequest;
import xyz.wbsite.zentao.sdk.task.req.ZtTaskCreateRequest;
import xyz.wbsite.zentao.sdk.task.req.ZtTaskDeleteRequest;
import xyz.wbsite.zentao.sdk.task.req.ZtTaskFinishRequest;
import xyz.wbsite.zentao.sdk.task.req.ZtTaskStartRequest;
import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskCloseResponse;
import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskCreateResponse;
import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskDeleteResponse;
import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskFinishResponse;
import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskGetResponse;
import xyz.wbsite.zentao.sdk.task.rsp.ZtTaskStartResponse;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

/**
 * 禅道任务服务
 *
 * @author wangbing
 * @version 0.0.1
 * @since 1.8
 */
public class ZtTaskService {

    private ZentaoInstance zentaoInstance;

    public ZtTaskService(ZentaoInstance zentaoInstance) {
        this.zentaoInstance = zentaoInstance;
    }

    /**
     * 创建任务
     */
    public ZtTaskCreateResponse create(ZtTaskCreateRequest ztTaskCreateRequest) {
        ZtTaskCreateResponse response = new ZtTaskCreateResponse();
        try {
            String url = StrUtil.format("/task-create-{}-0-0.json", ztTaskCreateRequest.getExecution());
            StaticLog.info(url);
            HttpRequest httpRequest = zentaoInstance.createPost(url);
            httpRequest.form("execution", ztTaskCreateRequest.getExecution());
            httpRequest.form("type", ztTaskCreateRequest.getType());
            httpRequest.form("module", ztTaskCreateRequest.getModule());
            httpRequest.form("assignedTo[]", StrUtil.join(",", ztTaskCreateRequest.getAssignedTo()));
            httpRequest.form("teamMember", ztTaskCreateRequest.getTeamMember());
            httpRequest.form("multiple", ztTaskCreateRequest.getMultiple());
            httpRequest.form("mode", ztTaskCreateRequest.getMode());
            httpRequest.form("status", "wait");
            httpRequest.form("story", ztTaskCreateRequest.getStory());
            httpRequest.form("color", ztTaskCreateRequest.getColor());
            httpRequest.form("name", ztTaskCreateRequest.getName());
            httpRequest.form("storyEstimate", ztTaskCreateRequest.getStoryEstimate());
            httpRequest.form("storyDesc", ztTaskCreateRequest.getStoryDesc());
            httpRequest.form("storyPri", ztTaskCreateRequest.getStoryPri());
            httpRequest.form("pri", ztTaskCreateRequest.getPri());
            httpRequest.form("estimate", ztTaskCreateRequest.getEstimate());
            httpRequest.form("desc", ztTaskCreateRequest.getDesc());
            httpRequest.form("estStarted", ztTaskCreateRequest.getEstStarted());
            httpRequest.form("deadline", ztTaskCreateRequest.getDeadline());
            httpRequest.form("after", "toTaskList");
            httpRequest.form("team[]", "");
            httpRequest.form("teamSource[]", "");
            httpRequest.form("teamEstimate[]", "");
            if (CollUtil.isNotEmpty(ztTaskCreateRequest.getMailtos())) {
                for (String mailto : ztTaskCreateRequest.getMailtos()) {
                    httpRequest.form("mailto[]", mailto);
                }
            }
            httpRequest.form("uid", RandomUtil.randomString(13));
            HttpResponse execute = httpRequest.execute();
            if (HttpStatus.HTTP_OK != execute.getStatus()) {
                response.setSuccess(false);
                response.setMessage("请求失败");
                return response;
            }
            String body = Convert.unicodeToStr(execute.body());
            StaticLog.info(body);
            // {"result":"success","message":"保存成功","id":"1891"}
            if (body.contains(Constant.SUCCESS_KEY)) {
                JSONObject entries = JSONUtil.parseObj(body);
                response.setId(Convert.toInt(entries.get("id")));
                response.setSuccess(true);
                response.setMessage("请求成功");
                return response;
            } else {
                response.setSuccess(false);
                response.setMessage(JSONUtil.parseObj(body).getStr("message"));
                return response;
            }
        } catch (HttpException e) {
            StaticLog.error(e);
        }
        response.setSuccess(false);
        response.setMessage("请求失败");
        return response;
    }

    /**
     * 关闭执行
     */
    public ZtTaskStartResponse start(ZtTaskStartRequest projectStartRequest) {
        ZtTaskStartResponse response = new ZtTaskStartResponse();
        try {
            String url = StrUtil.format("/task-start-{}.html", projectStartRequest.getTaskId());
            StaticLog.info(url);
            HttpRequest httpRequest = zentaoInstance.createPost(url);
            httpRequest.form("assignedTo", projectStartRequest.getAssignedTo());
            httpRequest.form("realStarted", projectStartRequest.getRealStarted());
            httpRequest.form("consumed", projectStartRequest.getConsumed());
            httpRequest.form("left", projectStartRequest.getLeft());
            httpRequest.form("status", "doing");
            httpRequest.form("comment", projectStartRequest.getComment());
            httpRequest.form("uid", RandomUtil.randomString(13));
            HttpResponse execute = httpRequest.execute();
            if (HttpStatus.HTTP_OK != execute.getStatus()) {
                response.setSuccess(false);
                response.setMessage("请求失败");
                return response;
            }
            String body = Convert.unicodeToStr(execute.body());
            // 返回html
            StaticLog.info(body);
        } catch (HttpException e) {
            StaticLog.error(e);
        }
        response.setSuccess(false);
        response.setMessage("请求失败");
        return response;
    }

    /**
     * 完成任务
     */
    public ZtTaskFinishResponse finish(ZtTaskFinishRequest ztTaskFinishRequest) {
        ZtTaskFinishResponse response = new ZtTaskFinishResponse();
        try {
            String url = StrUtil.format("/task-finish-{}.html", ztTaskFinishRequest.getTaskId());
            StaticLog.info(url);
            HttpRequest httpRequest = zentaoInstance.createPost(url);
            httpRequest.form("currentConsumed", ztTaskFinishRequest.getCurrentConsumed());
            httpRequest.form("consumed", ztTaskFinishRequest.getConsumed());
            httpRequest.form("assignedTo", ztTaskFinishRequest.getAssignedTo());
            httpRequest.form("realStarted", ztTaskFinishRequest.getRealStarted());
            httpRequest.form("finishedDate", ztTaskFinishRequest.getFinishedDate());
            httpRequest.form("status", "done");
            httpRequest.form("comment", ztTaskFinishRequest.getComment());
            httpRequest.form("uid", RandomUtil.randomString(13));
            HttpResponse execute = httpRequest.execute();
            if (HttpStatus.HTTP_OK != execute.getStatus()) {
                response.setSuccess(false);
                response.setMessage("请求失败");
                return response;
            }
            String body = Convert.unicodeToStr(execute.body());
            StaticLog.info(body);
            if (body.contains(Constant.SUCCESS_KEY)) {
                JSONObject entries = JSONUtil.parseObj(body);
                response.setId(Convert.toInt(entries.get("id")));
                response.setSuccess(true);
                response.setMessage("请求成功");
                return response;
            }
        } catch (HttpException e) {
            StaticLog.error(e);
        }
        response.setSuccess(false);
        response.setMessage("请求失败");
        return response;
    }

    /**
     * 关闭任务
     */
    public ZtTaskCloseResponse close(ZtTaskCloseRequest projectCloseRequest) {
        ZtTaskCloseResponse response = new ZtTaskCloseResponse();
        try {
            String url = StrUtil.format("/task-close-{}.html", projectCloseRequest.getTaskId());
            StaticLog.info(url);
            HttpRequest httpRequest = zentaoInstance.createPost(url);
            httpRequest.form("status", "closed");
            httpRequest.form("comment", projectCloseRequest.getComment());
            httpRequest.form("uid", RandomUtil.randomString(13));
            HttpResponse execute = httpRequest.execute();
            if (HttpStatus.HTTP_OK != execute.getStatus()) {
                response.setSuccess(false);
                response.setMessage("请求失败");
                return response;
            }
            String body = Convert.unicodeToStr(execute.body());
            StaticLog.info(body);
            if (body.contains(Constant.SUCCESS_KEY)) {
                JSONObject entries = JSONUtil.parseObj(body);
                response.setId(Convert.toInt(entries.get("id")));
                response.setSuccess(true);
                response.setMessage("请求成功");
                return response;
            }
        } catch (HttpException e) {
            StaticLog.error(e);
        }
        response.setSuccess(false);
        response.setMessage("请求失败");
        return response;
    }

    /**
     * 删除执行
     */
    public ZtTaskDeleteResponse delete(ZtTaskDeleteRequest projectDeleteRequest) {
        ZtTaskDeleteResponse response = new ZtTaskDeleteResponse();
        try {
            String url = StrUtil.format("/task-delete-{}.html", projectDeleteRequest.getTaskId());
            StaticLog.info(url);
            HttpRequest httpRequest = zentaoInstance.createPost(url);
            HttpResponse execute = httpRequest.execute();
            if (HttpStatus.HTTP_OK != execute.getStatus()) {
                response.setSuccess(false);
                response.setMessage("请求失败");
                return response;
            }
            String body = Convert.unicodeToStr(execute.body());
            StaticLog.info(body);
            response.setSuccess(true);
            response.setMessage("请求成功");
            return response;
        } catch (HttpException e) {
            StaticLog.error(e);
        }
        response.setSuccess(false);
        response.setMessage("请求失败");
        return response;
    }

    /**
     * 设置查询条件
     * <p>
     * 禅道查询条件是设置在session中的，所有查询之前先设置参数
     */
    private boolean setQuery(int executionId, String fieldName, String fieldValue) {
        try {
            String url = StrUtil.format("/search-buildQuery.html");
            StaticLog.info(url);
            HttpRequest httpRequest = zentaoInstance.createPost(url);
            httpRequest.form("fieldname", "");
            httpRequest.form("fieldstatus", "");
            httpRequest.form("fielddesc", "");
            httpRequest.form("fieldassignedTo", "");
            httpRequest.form("fieldpri", 0);
            httpRequest.form("fieldexecution", "");
            httpRequest.form("fieldmodule", "ZERO");
            httpRequest.form("fieldestimate", "");
            httpRequest.form("fieldleft", "");
            httpRequest.form("fieldconsumed", "");
            httpRequest.form("fieldtype", "");
            httpRequest.form("fieldfromBug", "");
            httpRequest.form("fieldclosedReason", "");
            httpRequest.form("fieldopenedBy", "");
            httpRequest.form("fieldfinishedBy", "");
            httpRequest.form("fieldclosedBy", "");
            httpRequest.form("fieldcanceledBy", "");
            httpRequest.form("fieldlastEditedBy", "");
            httpRequest.form("fieldmailto", "");
            httpRequest.form("fieldopenedDate", "");
            httpRequest.form("fielddeadline", "");
            httpRequest.form("fieldestStarted", "");
            httpRequest.form("fieldrealStarted", "");
            httpRequest.form("fieldassignedDate", "");
            httpRequest.form("fieldfinishedDate", "");
            httpRequest.form("fieldclosedDate", "");
            httpRequest.form("fieldcanceledDate", "");
            httpRequest.form("fieldlastEditedDate", "");
            httpRequest.form("fieldactivatedDate", "");
            httpRequest.form("fieldid", "");
            httpRequest.form("andOr1", "AND");
            httpRequest.form("field1", fieldName);
            httpRequest.form("operator1", "=");
            httpRequest.form("value1", fieldValue);
            httpRequest.form("andOr2", "and");
            httpRequest.form("field2", "id");
            httpRequest.form("operator2", "=");
            httpRequest.form("value2", "");
            httpRequest.form("andOr3", "and");
            httpRequest.form("field3", "status");
            httpRequest.form("operator3", "=");
            httpRequest.form("value3", "");
            httpRequest.form("groupAndOr", "and");
            httpRequest.form("andOr4", "AND");
            httpRequest.form("field4", "desc");
            httpRequest.form("operator4", "include");
            httpRequest.form("value4", "");
            httpRequest.form("andOr5", "and");
            httpRequest.form("field5", "assignedTo");
            httpRequest.form("operator5", "=");
            httpRequest.form("value5", "");
            httpRequest.form("andOr6", "and");
            httpRequest.form("field6", "pri");
            httpRequest.form("operator6", "=");
            httpRequest.form("value6", 0);
            httpRequest.form("module", "task");
            httpRequest.form("actionURL", StrUtil.format("/execution-task-{}-bySearch-myQueryID.html", executionId));
            httpRequest.form("groupItems", "3");
            httpRequest.form("formType", "lite");
            StaticLog.info(JSONUtil.toJsonStr(httpRequest.form()));
            HttpResponse execute = httpRequest.execute();
            if (HttpStatus.HTTP_OK != execute.getStatus()) {
                return false;
            }
            String body = Convert.unicodeToStr(execute.body());
            StaticLog.info(body);
            return execute.getStatus() == HttpStatus.HTTP_OK;
        } catch (Exception e) {
            StaticLog.error(e);
        }
        return false;
    }

    /**
     * 通过任务名称获取任务
     *
     * @param executionId 执行ID
     * @param taskId      任务ID
     * @return 任务获取响应
     */
    public ZtTaskGetResponse getById(int executionId, int taskId) {
        ZtTaskGetResponse response = new ZtTaskGetResponse();
        try {
            boolean setQuery = setQuery(executionId, "id", String.valueOf(taskId));
            if (!setQuery) {
                response.setSuccess(false);
                response.setMessage("设置查询参数失败");
                return response;
            }
            String url = StrUtil.format("/execution-task-{}-bySearch-myQueryID.html", executionId);
            StaticLog.info(url);
            HttpRequest httpRequest = zentaoInstance.createGetForHtml(url);
            HttpResponse execute = httpRequest.execute();
            if (HttpStatus.HTTP_OK != execute.getStatus()) {
                response.setSuccess(false);
                response.setMessage("请求失败");
                return response;
            }
            String body = execute.body();
            Document parse = Jsoup.parse(body);
            Elements trs = parse.select("#taskList tbody tr");
            if (trs.size() == 1) {
                Element tr = trs.get(0);
                ZtTask ztTask = new ZtTask();
                ztTask.setId(Convert.toInt(tr.select(".c-id").text()));
                ztTask.setName(tr.select(".c-name").attr("title"));
                ztTask.setStatus(tr.select(".c-status").text());
                ztTask.setPri(tr.select(".c-pri").text());
                ztTask.setAssignedTo(tr.select(".c-assignedTo").text());
                ztTask.setStatus(tr.select(".c-status").text());
                ztTask.setFinishedBy(tr.select(".c-finishedBy").text());
                ztTask.setProgress(tr.select("c-deadline").text());
                ztTask.setProgress(tr.select("c-estimate").text());
                ztTask.setProgress(tr.select("c-consumed").text());
                ztTask.setProgress(tr.select("c-left").text());
                ztTask.setProgress(tr.select("c-progress").text());
                response.setSuccess(true);
                response.setMessage("请求成功");
                response.setResult(ztTask);
                return response;
            }
            StaticLog.info(body);
            response.setMessage("无数据");
            return response;
        } catch (HttpException e) {
            StaticLog.error(e);
        }
        response.setSuccess(false);
        response.setMessage("请求失败");
        return response;
    }

    /**
     * 通过任务名称获取任务
     *
     * @param executionId 执行ID
     * @param name        任务名称
     * @return 任务获取响应
     */
    public ZtTaskGetResponse getByName(int executionId, String name) {
        ZtTaskGetResponse response = new ZtTaskGetResponse();
        try {
            boolean setQuery = setQuery(executionId, "name", name);
            if (!setQuery) {
                response.setSuccess(false);
                response.setMessage("设置查询参数失败");
                return response;
            }
            String url = StrUtil.format("/execution-task-{}-bySearch-myQueryID.html", executionId);
            StaticLog.info(url);
            HttpRequest httpRequest = zentaoInstance.createGetForHtml(url);
            HttpResponse execute = httpRequest.execute();
            if (HttpStatus.HTTP_OK != execute.getStatus()) {
                response.setSuccess(false);
                response.setMessage("请求失败");
                return response;
            }
            String body = execute.body();
            Document parse = Jsoup.parse(body);
            Elements trs = parse.select("#taskList tbody tr");
            if (trs.size() == 1) {
                Element tr = trs.get(0);
                ZtTask ztTask = new ZtTask();
                ztTask.setId(Convert.toInt(tr.select(".c-id").text()));
                ztTask.setName(tr.select(".c-name").attr("title"));
                ztTask.setStatus(tr.select(".c-status").text());
                ztTask.setPri(tr.select(".c-pri").text());
                ztTask.setAssignedTo(tr.select(".c-assignedTo").text());
                ztTask.setStatus(tr.select(".c-status").text());
                ztTask.setFinishedBy(tr.select(".c-finishedBy").text());
                ztTask.setProgress(tr.select("c-deadline").text());
                ztTask.setProgress(tr.select("c-estimate").text());
                ztTask.setProgress(tr.select("c-consumed").text());
                ztTask.setProgress(tr.select("c-left").text());
                ztTask.setProgress(tr.select("c-progress").text());
                response.setSuccess(true);
                response.setMessage("请求成功");
                response.setResult(ztTask);
                return response;
            }
            StaticLog.info(body);
            response.setMessage("无数据");
            return response;
        } catch (HttpException e) {
            StaticLog.error(e);
        }
        response.setSuccess(false);
        response.setMessage("请求失败");
        return response;
    }
}
